
package de.dtools.n2g.core;

/**
 *	@project:	note2go
 *	@author:	D.Toepel
 *	@version:	2009-08-04
 *	@note:		---
 *	
 *	Copyright (C) 2009  D.Toepel <de.dtools> {at} <gmail> {dot} <com>
 *	
 *	This program is free software: you can redistribute it and/or modify
 *	it under the terms of the GNU General Public License as published by
 *	the Free Software Foundation, either version 3 of the License, or
 *	(at your option) any later version.
 *	
 *	This program is distributed in the hope that it will be useful,
 *	but WITHOUT ANY WARRANTY; without even the implied warranty of
 *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *	GNU General Public License for more details.
 *	
 *	You should have received a copy of the GNU General Public License
 *	along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *	
 */


import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
import java.util.Vector;

public class LabelModel extends DefaultTreeModel  {
 
	private static final long serialVersionUID = 1L;
    private Vector<TreeModelListener> treeModelListeners =
        new Vector<TreeModelListener>();
    private Object[] nodesToRoot;
    private Label rootLabel;

    public LabelModel(Label root) {
    	super(root);
    	this.rootLabel = root;
        initTree();
    }
    
    private void initTree(){
    	DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode(rootLabel);
    	for (Label l : rootLabel.subLabels) {
    		
    		if (l.getChildCount() > 0){
    			buildTree(rootNode, l);
    		}else{
    			DefaultMutableTreeNode subDmtn = 
        			new DefaultMutableTreeNode(l);
    			rootNode.add(subDmtn);
    		}
		}
    }
    
    private void buildTree(DefaultMutableTreeNode node, Label label){
    	DefaultMutableTreeNode dmtn = 
    		new DefaultMutableTreeNode(label);
    	for (Label l : label.subLabels) {
    		
    		if (l.getChildCount() > 0){
    			buildTree(dmtn, l);
    		}else{
    			DefaultMutableTreeNode subDmtn = 
        			new DefaultMutableTreeNode(l);
        		dmtn.add(subDmtn);
    		}
		}
    	node.add(dmtn);
    }
    
    public void addChild(Label parent, Label child){
    	Label.linkLabels(parent, new Label[] {child});
    	fireTreeStructureChanged(rootLabel);
    }
    
    public void addAllChildren(Label parent, Label[] children){
    	Label.linkAllLabels(parent, children);
    	fireTreeStructureChanged(rootLabel);
    }
    
    public void addResultChildren(Label[] nodes, Label[] leafs){
    	Label.linkLabelResult(nodes, leafs);
    	fireTreeStructureChanged(rootLabel);
    }
    
    public void removeAllChildren(){
    	Label oldRoot = rootLabel;
    	this.rootLabel = new Label(rootLabel.getName(), rootLabel.getLabelID());
    	fireTreeStructureChanged(oldRoot);
    }

    public void removeAllChildren(Label parent){
    	parent.subLabels.removeAllElements();
		fireTreeStructureChanged(rootLabel);
    }

	public void removeChild(Label parent, Label child) {
		parent.subLabels.remove(child);
		fireTreeStructureChanged(rootLabel);
	}
	
	public Object[] getTreePathToRoot(TreeNode node){
		Object[] path = {(TreeNode)rootLabel};
		findChildPath(path, rootLabel, (Label)node);
		return nodesToRoot;
	}
	
	private void findChildPath(Object[] path, Label label, Label find){
		
		for(Label l : label.subLabels){
			Object[] newPath = new Object[path.length + 1];
			for (int i = 0; i < path.length; i++) {
				newPath[i] = path[i];
			}
			newPath[path.length] = (Object)l;
			if (l.getName() == find.getName()){
				nodesToRoot = newPath;
			}
			else{
				findChildPath(newPath,l,find);
			}
		}
	}

//////////////// Fire events //////////////////////////////////////////////

    /**
     * The only event raised by this model is TreeStructureChanged with the
     * root as path, i.e. the whole tree has changed.
     */
    protected void fireTreeStructureChanged(Label oldRoot) {
        TreeModelEvent e = new TreeModelEvent(this, new Object[] {oldRoot});
        for (TreeModelListener tml : treeModelListeners) {
            tml.treeStructureChanged(e);
        }
    }


//////////////// TreeModel interface implementation ///////////////////////

    /**
     * Adds a listener for the TreeModelEvent posted after the tree changes.
     */
    public void addTreeModelListener(TreeModelListener l) {
        treeModelListeners.addElement(l);
    }


}
